'''
    Code Name: Python Move Character 3D
    
    Module: PyMoveCharacter.Character
    Filename:  __init__.py
    
    Developed by: Juan C. Montes
    
    Created on 26/03/2009
'''


# Referencias de OGRE
import ogre.renderer.OGRE as ogre
import ogre.io.OIS as ois


''' Clase principal para controlar un character '''
class Character:    
    
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Function: Constructor
    '''
    def __init__(self, scenemanager, CharName):
        # Definimos los objetos    
        self.scenemanager = ogre.SceneManager
        self.mainNode = ogre.SceneNode
        self.charNode = ogre.SceneNode
        self.camNode = ogre.SceneNode
        self.camera = ogre.Camera        
        self.entPJ = ogre.Entity 
        
        # Definimos las animaciones
        self.animWalk = ogre.AnimationState           
        self.animIdle = ogre.AnimationState
        self.animKick = ogre.AnimationState
        
        # Asignamos los parametros
        self.scenemanager = scenemanager
        self.charName = CharName
        
    
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Function: addToScene
    Descript: Situa el char en la escena
    ''' 
    def addToScene(self, camera):   
        # Creamos la estructura para controlar el PJ en 3a persona
        self.mainNode = self.scenemanager.getRootSceneNode()\
                        .createChildSceneNode(self.charName)
        
        # Creamos los dos nodos pertenecientes al nodo principal      
        self.charNode = self.mainNode.createChildSceneNode(
                        '%s_char' % self.charName)
        self.camNode = self.mainNode.createChildSceneNode(
                        '%s_cam' % self.charName)
        
        # Insertamos el PJ en su nodo        
        self.entPJ = self.scenemanager.createEntity(self.charName, "ninja.mesh")
        self.charNode.attachObject(self.entPJ)
        self.charNode.setScale(0.2, 0.2, 0.2)
        self.animationState = self.entPJ.getAnimationState("Idle1")
        
        # Insertamos la camara en 3a persona
        self.camera = camera
        self.camNode.attachObject(self.camera)                
        
        # Posicionamos el nodo en el centro del mapa
        self.mainNode.setPosition(466.60, 150.00, 614.55)
        
        # Cargamos las animaciones
        self.loadAnim()
        
    
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Function: moveChar
    Descript: Mueve el char por la escena
    '''  
    def moveChar(self, scaleMove, rotX, rotY):
        self.mainNode.translate(scaleMove, ogre.Node.TS_LOCAL)
        self.mainNode.pitch(rotY)
        self.mainNode.yaw(rotX)  
                

    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Function: loadAnim
    Descript: Carga las animaciones del PJ
    '''     
    def loadAnim(self):
        self.animWalk = self.entPJ.getAnimationState("Walk")
        self.animWalk.setEnabled(False)
        self.animIdle = self.entPJ.getAnimationState("Idle2")
        self.animIdle.setLoop(True)
        self.animIdle.setEnabled(False)
        self.animKick = self.entPJ.getAnimationState("Kick")
        self.animKick.setEnabled(False)  
        
    
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Function: disableAnimations
    Descript: Carga las animaciones del PJ
    '''     
    def disableAnimations(self):
        self.animWalk.setEnabled(False)
        self.animIdle.setEnabled(False)
        self.animKick.setEnabled(False) 
    
        
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Function: updateChar
    Descript: Mueve el char por la escena
    ''' 
    def updateChar(self, elapsedTime, keyboard, mouse):  
        # Ninguna animacion esta en loop
        self.disableAnimations()
        animationState = ogre.AnimationState
        animationState = self.animIdle
                            
        # Forward
        if keyboard.isKeyDown(ois.KC_W):
            if keyboard.isKeyDown(ois.KC_LSHIFT):
                animationState = self.animWalk            
                self.mainNode.translate(
                                    self.mainNode.getOrientation() * 
                                    ogre.Vector3(0, 0, -100 * elapsedTime * 2))
            else:
                animationState = self.animWalk                  
                self.mainNode.translate(
                                    self.mainNode.getOrientation() * 
                                    ogre.Vector3(0, 0, -100 * elapsedTime))     
        
        # Back
        elif keyboard.isKeyDown(ois.KC_X) or keyboard.isKeyDown(ois.KC_S):
            animationState = self.animWalk             
            self.mainNode.translate(
                                    self.mainNode.getOrientation() * 
                                    ogre.Vector3(0, 0, 50 * elapsedTime))   
        
        # Obtenemos el estado del raton
        mouseState = ois.MouseState
        mouseState = mouse.getMouseState()
        
        # Left
        if keyboard.isKeyDown(ois.KC_A):
            if not mouseState.buttonDown(ois.MB_Right):
                self.mainNode.yaw(ogre.Radian(2 * elapsedTime))
            else:
                animationState = self.animWalk                
                self.mainNode.translate(
                                    self.mainNode.getOrientation() * 
                                    ogre.Vector3(-50 * elapsedTime, 0, 0))
                
        # Right
        elif keyboard.isKeyDown(ois.KC_D):
            if not mouseState.buttonDown(ois.MB_Right):
                self.mainNode.yaw(ogre.Radian(-2 * elapsedTime))
            else:                
                animationState = self.animWalk                 
                self.mainNode.translate(
                                    self.mainNode.getOrientation() * 
                                    ogre.Vector3(50 * elapsedTime, 0, 0))    
                
        # Kick
        if keyboard.isKeyDown(ois.KC_SPACE):            
            animationState = self.animKick           
        
        # Controlamos el raton para girar la camara y el PJ
        if mouseState.buttonDown(ois.MB_Right):
            # Obtenemos el movimiento del raton
            rotX = ogre.Degree(-mouseState.X.rel * 20)
            rotY = ogre.Degree(-mouseState.Y.rel * 20)
            
            # Lo aplicamos sobre los nodos
            self.camNode.pitch(rotY * elapsedTime)
            self.mainNode.yaw(rotX * elapsedTime)
            
        # Mostramos la animacion seleccionada    
        #if self.animationState.hasEnded():      
        animationState.setEnabled(True)
        animationState.addTime(elapsedTime)                                     
    
    
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    Function: setVisible
    Descript: Define si el PJ es visible o no
    ''' 
    def setVisible(self, visible):
        self.mainNode.setVisible(visible)
    
            
        
        
        
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
        